/*
 *	Trabalho 2 - Hospital em ICMCTown
 *	Programacao Concorrente - SCC0143 - 2014
 *
 *	Henrique Teixeira Arroyo	6419241
 *	Henry D. Leão				5881632
 *	Júlio Zanzini Polzato		7288971
 * 
 *  - Versão sequencial do algoritmo utilizado
 * 
 */

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>

#define MAX_WEIGHT 1000000000

#define min(a,b) a>b? b : a

// Funcao imprime a matriz D de dimensao V
void print(int *D, int V){
	int i,j;
	
	for(i=0;i<V;i++){
		for(j=0;j<V;j++)
			printf("%d ",D[i*V+j]);
		printf("\n");
	}
}

// Funcao ordena o vetor 'a' e realiza as mesmas operacoes no vetor 'b'
// os dois vetores devem ter dimensao N
void sort(int *a, int*b, int N){
	int xa, xb, i, j, aux;
	for(i=0;i<N;i++){
		xa = a[i];
		xb = b[i];
		j = i;
		while(j>0 && a[j-1] < xa){
			a[j] = a[j-1];
			b[j] = b[j-1];
			j--;
		}
		a[j] = xa;
		b[j] = xb;
	}
}

// Funcao encontra as distancias minimas entre os vertices utilizando Floyd-Warshall
void minPathFW(int *D, int V){
	int i,j,k;
	
	for(i=0;i<V;i++)
		for(j=0;j<V;j++)
			if(D[i*V+j] != MAX_WEIGHT)
				for(k=0;k<V;k++)
					D[i*V+k] = min(D[i*V+k],D[i*V+j]+D[j*V+k]);
			
}

int main(){
	
	int i, j, V, E, b;
	int ns = 1;
	float aL,L = MAX_WEIGHT;
	scanf("%d %d",&V,&E);
	
	int *aw = (int*)malloc(sizeof(int)*V);
	int *bw = (int*)malloc(sizeof(int)*V);
	int *S = (int*)malloc(sizeof(int)*V);
	int *source = (int*)malloc(sizeof(int)*E);
	int *target = (int*)malloc(sizeof(int)*E);
	S[0] = 0;
	
	// Aloca matriz de pesos
	int *A = (int*)malloc(sizeof(int)*(V*V));
	// Aloca matriz de distancias
	int *D = (int*)malloc(sizeof(int)*(V*V));
	
	// Inicializa matriz de distancias
	for(i=0;i<V;i++){
		for(j=0;j<V;j++){
			if(i==j)
				D[i*V+j] = 0;
			else
				D[i*V+j] = MAX_WEIGHT;
		}
	}
	
	// Le as arestas e preenche matriz
	int n1, n2, p;
	for(i=0;i<E;i++){
		scanf("%d %d %d",&n1,&n2,&p);
		D[(n1-1)*V+(n2-1)] = p;
		D[(n2-1)*V+(n1-1)] = p;
		
		source[i] = n1-1;
		target[i] = n2-1;
	}
	
	// Salva pesos iniciais na matriz de pesos
	for(i=0;i<V*V;i++)
		A[i] = D[i];
	
	// Executa Floyd-Warshall
	minPathFW(D,V);
	
	// Executa algoritmo para encontrar o raio do centro absoluto
	for(i=0;i<E;i++){
		// Encontra o par (a,b) para cada vertice
		for(j=0;j<V;j++){
			aw[j] = D[source[i]*V+j];
			bw[j] = D[target[i]*V+j];
		}
	
		// Ordena conjunto de pontos
		sort(aw,bw,V);
		
		// Encontra vertices que entram no conjunto S (reducao).
		b = bw[0];
		ns = 1;
		for(j=1;j<V;j++){
			if(bw[j]>b){
				S[ns] = j;
				ns++;
				b = bw[j];
			}
		}
		
		// Calcula interseccoes (L) e guarda o menor valor que será o raio desejado.
		for(j=0;j<ns-1;j++){
			aL = ( A[ source[i]*V + target[i] ] + bw[S[j]] + aw[S[j+1]] )*0.5;
			if(aL < L)
				L = aL;
		}
	}
	
	// Imprimindo resultado
	printf("%.2f\n",L);
	
	return 0;
}